home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacGames Sampler
/
PHT MacGames Bundle.iso
/
MacSource Folder
/
Samples from the CD
/
C and C++
/
Gnuplot 3.5 for Macintosh
/
SOURCES 3.5
/
term
/
mif.trm
< prev
next >
Wrap
Text File
|
1993-11-12
|
20KB
|
641 lines
/* GNUPLOT -- mif.trm */
/*
* Copyright (C) 1992, 1993
*
* Permission to use, copy, and distribute this software and its
* documentation for any purpose with or without fee is hereby granted,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.
*
* Permission to modify the software is granted, but not the right to
* distribute the modified code. Modifications are to be distributed
* as patches to released version.
*
* This software is provided "as is" without express or implied warranty.
*
* This file is included by ../term.c.
*
* This terminal driver was developed for
* gnuplot for unix version 3.0 (patchlevel 1)
* gnuplot for unix version 3.2 (patchlevel 2)
*
* This terminal driver supports:
* Frame Maker MIF format version 3.00
*
* Options for this terminal driver (set terminal mif [options]):
* colour / Draw primitives with line types >= 0 in colour (sep. 2-7)
* monochrome Draw primitives in black (sep. 0)
*
* polyline / Draw lines as continous curves
* vectors Draw lines as collections of vectors
*
* help / ? Print short usage description on stderr
*
* Properties for this terminal driver:
* -Gnuplot size of worksheet: MIF_XMAX * MIF_YMAX
* -Unit in MIF output: cm
* -Plot primitives with the same pen will
* be grouped in the same MIF group.
* -Plot primitives with line types >= 0
* will as default be drawn in colour.
* -Lines are plotted as collections of
* vectors, or as continous lines (default)
* -Plot primitives in a plot will be in a
* Frame in MIF. Several plot Frames will
* be collected in one large Frame.
* -Point size of MIF output characters: MIF_PSIZE
* -Used font for MIF output characters: Times
* -Supports vertical text
*
* AUTHORS:
* Olof Franksson, Physics IV, KTH, S-100 44 Stockholm, Sweden
*
* COMMENTS:
* Send comments and/or suggestions to olof@fysik4.kth.se
*
* CHANGES:
* Changed order of routine declarations. olof@fysik4.kth.se
* Changed mechanism for pen pattern selection. kssingvo@immd4.informatik.uni-erlangen.de
* Support for vertical text. kssingvo@immd4.informatik.uni-erlangen.de
* Fixed plot bug for "set size XS,YS", XS/YS > 1. olof@fysik4.kth.se
*
*/
#if !defined(cfree)
#define cfree free
#endif
/** Coordinates **/
#define GNP_TO_MIF(P) (((float) (P)) / 1000.0) /* Converts gnuplot units to MIF units */
#define MIF_XMAX 15000 /* Basic unit: 0.01 mm (15cm -> 15*10*100=15000) */
#define MIF_YMAX 10000 /* Basic unit: 0.01 mm (10cm -> 10*10*100=10000) */
#define MIF_XLAST (MIF_XMAX - 1)
#define MIF_YLAST (MIF_YMAX - 1)
static struct mif_line { /* Line point structure specification */
float fpos_x; /* Line point X coordinate */
float fpos_y; /* Y coordinate */
struct mif_line *next; /* Pointer to next line point */
struct mif_line *prev; /* Pointer to previous line point */
} mif_line = { /* Current position structure. Adjust for orign. Local for this file. */
GNP_TO_MIF(0),
GNP_TO_MIF(MIF_YLAST),
&mif_line,
&mif_line
};
/** Characters **/
#define MIF_PSIZE 9 /* Point size of used characters */
#define MIF_VCHAR (MIF_YMAX/31) /* Distance between rows (a guess) */
#define MIF_HCHAR (MIF_XMAX/95) /* Distance between characters (a guess) */
/** Scale marks **/
#define MIF_VTIC (MIF_YMAX/150) /* Size of scale mark (vert) */
#define MIF_HTIC (MIF_XMAX/225) /* Size of scale mark (hor) */
/** Drawing properties **/
static char mif_justify[64]; /* How to justify the used text */
static char mif_pen[64], mif_pen_width[64], mif_separation[64]; /* How to plot */
#define MIF_TEXT_HOR 0
#define MIF_TEXT_VER 1
static int mif_text_ang = MIF_TEXT_HOR; /* Rotation angle of text */
#define MIF_NPENS 16 /* Number of MIF pen types */
static int mif_pentype = 0; /* Pen type to use. Also used to create groups for graphics */
#define MIF_PEN_TO_GROUP(P) ( 1 + (P) ) /* Map pen type to group number. Must be >= 1 */
static int mif_pattern_table[MIF_NPENS] = { /* Table, which pattern should be used for drawing */
0, /* border */
1, /* not used */
2, 3, 4, 8, 12, 13, /* other lines: functions, data, ... (5 is used for grid; 6,7 is (nearly) invisible) */
5, /* grid */
9, 10, 11, 12, 13, 14, 15 /* not used */
};
/** MIF groups administration **/
#define MIF_NGROUP_ID 20
static struct mif_group_id {
int group_existance;
#define MIF_GROUP_EXISTS 1 /* This group id should generate a MIF group */
#define MIF_GROUP_NOT_EXISTS 0 /* This group id should not generate a MIF group */
int group_id;
#define MIF_INVALID_GROUP_ID 0 /* An invalid MIF group ID */
} mif_group_id[MIF_NGROUP_ID]; /* List of used group ID:s and corresponding MIF groups existance */
/** Semaphores **/
static int mif_initialized = 0; /* != 0 when output is active */
static int mif_in_frame = 0; /* != 0 when inside a plot frame */
static int mif_frameno = -1; /* Current frame number */
static int mif_colour = TRUE; /* == TRUE when colour should be used */
static int mif_polyline = TRUE; /* == TRUE when lines are drawn as continous curves */
/** Declaration of routine/s for internal use **/
static int insert_mif_line(), proc_group_id();
/** Routine/s **/
/* Called when this terminal type is set in order to parse options */
MIF_options()
{
extern char term_options[]; /* Declared in ../setshow.c */
if (!END_OF_COMMAND) {
/* Colour options */
if (!END_OF_COMMAND && almost_equals(c_token, "m$onochrome")) { /* Compare up to $ */
mif_colour = FALSE;
c_token++;
}
if (!END_OF_COMMAND && almost_equals(c_token, "c$olour")) { /* Compare up to $ */
mif_colour = TRUE;
c_token++;
}
/* Curve options */
if (!END_OF_COMMAND && almost_equals(c_token, "v$ectors")) { /* Compare up to $ */
mif_polyline = FALSE;
c_token++;
}
if (!END_OF_COMMAND && almost_equals(c_token, "p$olyline")) { /* Compare up to $ */
mif_polyline = TRUE;
c_token++;
}
/* Short help */
if ( !END_OF_COMMAND &&
(almost_equals(c_token, "h$elp") ||
almost_equals(c_token, "?$")) ) { /* Compare up to $ */
fprintf(stderr, "Usage: set terminal mif [options]\n");
fprintf(stderr, "\toptions:\n");
fprintf(stderr, "\t\tcolour / Draw primitives with line types >= 0 in colour (sep. 2-7)\n");
fprintf(stderr, "\t\tmonochrome Draw primitives in black (sep. 0) \n");
fprintf(stderr, "\n");
fprintf(stderr, "\t\tpolyline / Draw lines as continous curves \n");
fprintf(stderr, "\t\tvectors Draw lines as collections of vectors \n");
fprintf(stderr, "\n");
fprintf(stderr, "\t\thelp / ? Print short usage description on stderr \n");
c_token++;
}
}
sprintf(term_options, "%s %s", (mif_colour == TRUE)? "colour": "monochrome",
(mif_polyline == TRUE)? "polyline": "vectors");
}
/* Deallocate the used line structure elements */
static int free_mif_line()
{
struct mif_line *tline;
while (mif_line.prev != &mif_line) {
/* Unlink */
tline = mif_line.prev;
mif_line.prev = mif_line.prev->prev;
mif_line.prev->next = &mif_line;
/* Deallocate */
free(tline);
}
/* Make sure that the list will be empty */
mif_line.prev = &mif_line;
mif_line.next = &mif_line;
}
/* Draw the pending line. Change current position. */
static int put_mif_line()
{
int np, i;
struct mif_line *tline;
/* Process if inside a Frame */
if (mif_initialized != 0 && mif_in_frame != 0) {
/* Count the number of available points */
for (tline = mif_line.next, np = 1; tline != &mif_line; tline = tline->next, np++)
;
/* Draw line (at least two points) */
if (np >= 2) {
/* Line preamble */
fprintf(outfile, "\t<PolyLine <GroupID %d> %s %s %s\n",
MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
/* Draw the line elements */
fprintf(outfile, "\t\t<NumPoints %d> ", np);
for (i = 0, tline = &mif_line; i < np; i++, tline = tline->next) {
if (i%4 == 0)
fprintf(outfile, "\n\t\t");
fprintf(outfile, "<Point %.3f %.3f> ", tline->fpos_x, tline->fpos_y);
}
/* Line post amble */
fprintf(outfile, "\n\t>\n");
/* Register the used group ID */
proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
/* Avoid to redraw this. The MIF system should remember it. */
mif_pen[0] = '\0';
mif_pen_width[0] = '\0';
mif_separation[0] = '\0';
/* Move current position to end of line */
mif_line.fpos_x = mif_line.prev->fpos_x;
mif_line.fpos_y = mif_line.prev->fpos_y;
/* Restore the line */
free_mif_line();
}
} /* Line processed */
}
/* Set up a MIF output file */
MIF_init()
{
int i;
extern char version[]; /* Declared in ../version.c */
extern char patchlevel[];
/* Process if not inside a MIF file and Frame */
if (mif_initialized == 0 && mif_in_frame == 0) {
/* Tell this terminal driver that the output is initialized and no current frames are processed */
mif_initialized = 1;
mif_in_frame = 0;
/* Reset internal position */
free_mif_line();
mif_line.fpos_x = GNP_TO_MIF(0);
mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
/* Reset drawing properties strings */
mif_pen[0] = '\0';
mif_pen_width[0] = '\0';
mif_separation[0] = '\0';
sprintf(mif_justify, " <TLAlignment Left> ");
/* Reset group ID generator */
for (i = 0; i < MIF_NGROUP_ID; i++) {
mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
}
/* Identify ourselves */
fprintf(outfile, "<MIFFile 3.00> # Generated by gnuplot version %s patchlevel %s; identifies this as a MIF file\n", version, patchlevel);
fprintf(outfile, "#\n");
/* Setup a default environment to use */
fprintf(outfile, "# Set a default pen pattern, pen width, unit and font for subsequent objects\n");
fprintf(outfile, "<Pen 0>\n");
fprintf(outfile, "<Fill 15>\n");
fprintf(outfile, "<PenWidth 0.5 pt>\n");
fprintf(outfile, "<Separation 0>\n");
fprintf(outfile, "<Units Ucm>\n");
fprintf(outfile, "<Font <FFamily `Times'> <FSize %d> <FPlain Yes>>\n", MIF_PSIZE);
fprintf(outfile, "#\n");
} /* MIF file created */
}
/* Finish of a MIF output file */
MIF_reset()
{
/* Process if inside a MIF file and not inside a Frame */
if (mif_initialized != 0 && mif_in_frame == 0) {
/* Finish off the MIF file */
fprintf(outfile, "#\n");
fprintf(outfile, "# End of MIFFile\n");
/* Tell this terminal driver that the output is finished */
mif_initialized = 0;
} /* MIF file finished */
}
/* Start plotting a Frame (-> graphics mode) */
MIF_graphics()
{
int i;
/* Process if not inside a Frame */
if (mif_initialized != 0 && mif_in_frame == 0) {
/* Tell that this terminal driver is working with a plot frame */
mif_in_frame = 1;
/* Update frame number */
mif_frameno++;
/* Set current position */
free_mif_line();
mif_line.fpos_x = GNP_TO_MIF(0);
mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
/* Set drawing properties */
mif_pen[0] = '\0';
mif_pen_width[0] = '\0';
mif_separation[0] = '\0';
sprintf(mif_justify, " <TLAlignment Left> ");
/* Reset group ID generator */
for (i = 0; i < MIF_NGROUP_ID; i++) {
mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
}
/* Frame preamble */
fprintf(outfile, "#\n");
fprintf(outfile, "# Frame number %d with plot of graphics\n", mif_frameno);
fprintf(outfile, "<Frame\n");
fprintf(outfile, "\t<Pen 15>\n");
fprintf(outfile, "\t<Fill 15>\n");
fprintf(outfile, "\t<PenWidth 0.5 pt>\n");
fprintf(outfile, "\t<Separation 0>\n");
fprintf(outfile, "\t<BRect 0.000 %.3f %.3f %.3f>\n",
((float) mif_frameno)*GNP_TO_MIF(MIF_YMAX+100), GNP_TO_MIF(MIF_XMAX), GNP_TO_MIF(MIF_YMAX));
fprintf(outfile, "\t<NSOffset 0.000>\n");
fprintf(outfile, "\t<BLOffset 0.000>\n");
} /* Frame created */
}
/* Stop plotting a Frame (-> text mode) */
MIF_text()
{
int i;
/* Process if inside a Frame */
if (mif_initialized != 0 && mif_in_frame != 0) {
/* Draw pending line */
if (mif_polyline == TRUE)
put_mif_line();
/* Group the used plot primitives */
fprintf(outfile, "\t#\n");
fprintf(outfile, "\t# Group the the objects in groups to make the chart easier to manipulate\n");
fprintf(outfile, "\t# after it's imported into FrameMaker.\n");
for (i = 0; i < MIF_NGROUP_ID; i++) {
if (mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
mif_group_id[i].group_existance == MIF_GROUP_EXISTS) {
fprintf(outfile, "\t<Group\n");
fprintf(outfile, "\t\t<ID %d>\n", mif_group_id[i].group_id);
fprintf(outfile, "\t>\n");
}
}
/* Frame post amble */
fprintf(outfile, ">\n");
fprintf(outfile, "# End of Frame number %d\n", mif_frameno);
fprintf(outfile, "#\n");
/* Tell that this terminal driver is not working with a plot frame */
mif_in_frame = 0;
} /* Frame finshed */
}
/* Select type of line in grapics */
/* NOTE: actually written to output the first time a primitive is drawn AFTER this call */
MIF_linetype(linetype)
int linetype; /* -2=border, -1=X/Y-axis, 0-13=lines, and 14-=mapped back */
{
/* Process if inside a Frame */
if (mif_initialized != 0 && mif_in_frame != 0) {
/* Draw pending line */
if (mif_polyline == TRUE)
put_mif_line();
/* Translate gnuplot pen types to MIF pen types */
if (linetype < 0) { /* Special lines */
if (linetype == -1) {
mif_pentype = 8+MIF_NPENS; /* -1 */
if (mif_colour == TRUE)
sprintf(mif_separation, " <Separation 0> ");
}
else {
mif_pentype = 0+MIF_NPENS; /* -2 or less */
if (mif_colour == TRUE)
sprintf(mif_separation, " <Separation 0> ");
}
sprintf(mif_pen_width, " <PenWidth 1.0 pt> ");
}
else { /* Normal lines */
mif_pentype = (linetype)%MIF_NPENS; /* 0-(MIF_NPENS-1) */
sprintf(mif_pen_width, " <PenWidth 0.5 pt> ");
if (mif_colour == TRUE)
sprintf(mif_separation, " <Separation %d> ", 2+(mif_pentype%6)); /* 2-7 */
}
/* Set pen type */
sprintf(mif_pen, " <Pen %d> ", mif_pattern_table[mif_pentype%MIF_NPENS]);
} /* Primitive processed */
}
/* Draw the text horisontally or vertically (90 degrees counterclockwise) */
int MIF_text_angle(ang)
int ang;
{
if (ang != 0)
mif_text_ang = MIF_TEXT_VER;
else
mif_text_ang = MIF_TEXT_HOR;
return(TRUE);
}
/* Justify following text lines (MIF_put_text()) relative to the insertion point */
/* NOTE: actually written to output in text primitives which are drawn AFTER this call */
#ifdef THINK_C
int MIF_justify_text(enum JUSTIFY mode)
#else
MIF_justify_text(mode)
enum JUSTIFY mode;
#endif
{
int rval = TRUE;
/* Process if inside a Frame */
if (mif_initialized != 0 && mif_in_frame != 0) {
switch (mode) {
case LEFT:
sprintf(mif_justify, " <TLAlignment Left> ");
break;
case CENTRE:
sprintf(mif_justify, " <TLAlignment Center> ");
break;
case RIGHT:
sprintf(mif_justify, " <TLAlignment Right> ");
break;
default:
rval = FALSE;
break;
}
} /* Primitive processed */
else {
rval = FALSE;
}
return(rval);
}
/* Draw a vector from current position to (x, y) and change current position. */
/* NOTE: actually written to output the first time another primitive is called AFTER this call */
MIF_vector(x, y)
unsigned int x, y;
{
/* Process if inside a Frame */
if (mif_initialized != 0 && mif_in_frame != 0) {
/* Setup the vector as a part of the line */
insert_mif_line(GNP_TO_MIF(x), GNP_TO_MIF(MIF_YLAST-(int)y));
/* Draw pending line -> vector */
if (mif_polyline == FALSE)
put_mif_line();
} /* Vector processed */
}
/* Move current position */
MIF_move(x, y)
unsigned int x, y;
{
/* Process if inside a Frame */
if (mif_initialized != 0 && mif_in_frame != 0) {
/* Draw pending line */
if (mif_polyline == TRUE)
put_mif_line();
mif_line.fpos_x = GNP_TO_MIF(x);
mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST-(int)y);
}
}
/* Draw the text string str at (x, y). Adjust according to MIF_justify_text(). Change current position. */
MIF_put_text(x, y, str)
unsigned int x, y;
char str[];
{
/* Process if inside a Frame */
if (mif_initialized != 0 && mif_in_frame != 0) {
/* Draw pending line */
if (mif_polyline == TRUE)
put_mif_line();
/* Adjust current position for text-graphics alignment */
MIF_move(x, y-MIF_VCHAR/5);
if (strlen(str) > 0) {
/* Draw the text */
fprintf(outfile, "\t<TextLine <GroupID %d> %s %s %s\n",
MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
fprintf(outfile, "\t\t<TLOrigin %.3f %.3f> %s %s <String `%s'>\n",
mif_line.fpos_x, mif_line.fpos_y, mif_justify,
(mif_text_ang == MIF_TEXT_VER)? "<Angle 90>": "",
str);
fprintf(outfile, "\t>\n");
/* Register the used group ID */
proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
/* Avoid to redraw this. The MIF system should remember it. */
mif_pen[0] = '\0';
mif_pen_width[0] = '\0';
mif_separation[0] = '\0';
mif_justify[0] = '\0'; /* Independent of linetype */
}
} /* Text processed */
}
/* Insert one point in the line */
static int insert_mif_line(fx, fy)
float fx, fy;
{
int rval = TRUE;
if ((mif_line.prev->next = (struct mif_line *) alloc(sizeof(struct mif_line),"MIF driver")) != (struct mif_line *) NULL) {
/* Link */
mif_line.prev->next->next = &mif_line;
mif_line.prev->next->prev = mif_line.prev;
mif_line.prev = mif_line.prev->next;
/* Fill */
mif_line.prev->fpos_x = fx;
mif_line.prev->fpos_y = fy;
rval = TRUE;
}
else { /* Failed to allocate */
/* Relink */
mif_line.prev->next = &mif_line;
rval = FALSE;
}
return(rval);
}
/* Register group ID. Update group ID existance. */
/* Returns: 1 group_id belongs to a MIF group
0 group_id does not belong to a MIF group
-1 not inside a Frame
-2 group ID list is full
*/
static int proc_group_id(group_id)
int group_id;
{
int i, rval = 0;
/* Process if inside a Frame */
if (mif_initialized != 0 && mif_in_frame != 0) {
/* Find out the group ID, or a free group ID slot index. */
for (i = 0; i < MIF_NGROUP_ID &&
mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
mif_group_id[i].group_id != group_id;
i++) {
/* Don't check the group_existance variable */
}
if (i < MIF_NGROUP_ID) {
if (mif_group_id[i].group_id == MIF_INVALID_GROUP_ID) {
/* Register as new group ID for eventual use as MIF group */
mif_group_id[i].group_id = group_id;
mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
}
else {
/* If second use of this group ID -> create a new MIF group */
if (mif_group_id[i].group_id == group_id) {
mif_group_id[i].group_existance = MIF_GROUP_EXISTS;
/* NOTE: a group MUST have at least two members. */
rval = 1;
}
}
}
else {
rval = -2; /* No place for this group ID in the list */
}
} /* Group ID processed */
else {
rval = -1; /* Not inside a Frame */
}
/* Return MIF group status */
return(rval);
}